---
title: "Python AST笔记"
date: 2018-11-21
categories:
- python
tags:
---

<div id="content">
<div class="org-src-container">
<pre class="src src-py">#! python3
import ast
import json

def get_fields(obj):
    if not isinstance(obj, ast.AST):
	return None
    if len(obj._fields) &lt; 1:
	return None
    retn = {}
    for field in obj._fields:
	ele = {}
	ele["name"] = field
	ele["type"] = str(type(field))
	ele["sub"] = get_fields(getattr(obj, field))
	retn[field] = ele
    return retn

def pretty_print(obj, tab = 0):
    if not isinstance(obj, ast.AST):
	return
    if len(obj._fields) &lt; 1:
	return 
    for field in obj._fields:
	field_obj = getattr(obj, field)
	if isinstance(field_obj, str):
	    print("%s%s string value=%s" % (" " * tab, field, field_obj))
	elif isinstance(field_obj, list):
	    print("%s%s list[%d]" % (" " * tab, field, len(field_obj)))
	    for ele in field_obj:
		print("%s%s" % (" " * (tab + 4), str(type(ele))))
		pretty_print(ele, tab + 8)
	else:
	    print("%s%s %s" % (" " * tab, field, str(type(field_obj))))
	    pretty_print(field_obj, tab + 4)


expr = 'function(a, b)'
obj = ast.parse(expr, '', 'eval')
# obj &lt;_ast.Expression&gt;
#   |- body &lt;_ast.Call&gt;
#     |- func &lt;_ast.Name&gt;
#        |- id: function
#     |- args [&lt;_ast.Name&gt;]
#        |- args[0]
#          |- id: a
#        |- args[1]
#          |- id: b
obj = compile(expr, '', 'eval')
# obj &lt;code object &lt;module&gt;&gt;
# co_names: ('function', 'a', 'b')
# co_name: module

expr = 'md5("this is a const string", timestamp())'
obj = ast.parse(expr, '', 'eval')
# obj &lt;_ast.Expression&gt;
# `- body &lt;_ast.Call&gt;
#   `- func [_ast.Name]
#    `- id: 'md5'
#  `- args [&lt;_ast.Str]
#    |- args[0] &lt;_ast.Str&gt;
#      |- s: 'this is a const string'
#    |- args[1] &lt;_ast.Call&gt;
#      |- func &lt;_ast.Name&gt;
#      |- args []
obj = compile(expr, '', 'eval')
# obj &lt;code object &lt;module&gt;&gt;
# co_names: ('md5', 'timestamp')

expr = 'md5(R.MD5_SALT, timestamp())'
obj = ast.parse(expr, '', 'eval')
# obj &lt;_ast.Expression&gt;
#   |- body &lt;_ast.Call&gt;
#     |- func &lt;_ast.Name&gt;
#       |- id: 'md5'
#     |- args [&lt;_ast.Attribute&gt;]
#       |- args[0] &lt;_ast.Attirbute&gt;
#         |- attr: 'MD5_SALT'
#         |- value &lt;_ast.Name&gt;
#           |- id: 'R'
#       |- args[1] &lt;_ast.Call&gt;

expr = 'auth.md5()'
obj = ast.parse(expr, '', 'eval')
# pretty_print(obj)
# body &lt;class '_ast.Call'&gt;
#     func &lt;class '_ast.Attribute'&gt;
#         value &lt;class '_ast.Name'&gt;
#             id string value=auth
#             ctx &lt;class '_ast.Load'&gt;
#         attr string value=md5
#         ctx &lt;class '_ast.Load'&gt;
#     args &lt;class 'list'&gt;
#     keywords &lt;class 'list'&gt;

expr = 'R.SECURITY.MD5_SALT'
obj = ast.parse(expr, '', 'eval')
# obj &lt;_ast.Expression&gt;
# |- body &lt;_ast.Attribute&gt;
#   |- attr: 'MD5_SALT'
#   |- value: &lt;_ast.Attribute&gt;
#     |- attr: 'SECURITY'
#     |- value: &lt;_ast.Name&gt;
#       |- id: 'R'

expr = 'R["Security"]["MD5_SALT"]'
obj = ast.parse(expr, '', 'eval')
print(isinstance(obj.body, ast.Subscript))
# result of pretty_print(obj): 
# body &lt;class '_ast.Subscript'&gt;
#     value &lt;class '_ast.Subscript'&gt;
#         value &lt;class '_ast.Name'&gt;
#             id string value=R
#             ctx &lt;class '_ast.Load'&gt;
#         slice &lt;class '_ast.Index'&gt;
#             value &lt;class '_ast.Str'&gt;
#                 s string value=Security
#         ctx &lt;class '_ast.Load'&gt;
#     slice &lt;class '_ast.Index'&gt;
#         value &lt;class '_ast.Str'&gt;
#             s string value=MD5_SALT
#     ctx &lt;class '_ast.Load'&gt;            

expr = 'response.status == 200'
obj = ast.parse(expr, '', 'eval')
pretty_print(obj)
# body &lt;class '_ast.Compare'&gt;
#     left &lt;class '_ast.Attribute'&gt;
#         value &lt;class '_ast.Name'&gt;
#             id string value=response
#             ctx &lt;class '_ast.Load'&gt;
#         attr string value=status
#         ctx &lt;class '_ast.Load'&gt;
#     ops list[1]
#         &lt;class '_ast.Eq'&gt;
#     comparators list[1]
#         &lt;class '_ast.Num'&gt;
#             n &lt;class 'int'&gt;

expr = '500 &lt;= response.status'
obj = ast.parse(expr, '', 'eval')
pretty_print(obj)
# body &lt;class '_ast.Compare'&gt;
#     left &lt;class '_ast.Num'&gt;
#         n &lt;class 'int'&gt;
#     ops list[1]
#         &lt;class '_ast.LtE'&gt;
#     comparators list[1]
#         &lt;class '_ast.Attribute'&gt;
#             value &lt;class '_ast.Name'&gt;
#                 id string value=response
#                 ctx &lt;class '_ast.Load'&gt;
#             attr string value=status
#             ctx &lt;class '_ast.Load'&gt;
</pre>
</div>
</div>
<div class="status" id="postamble">
<p class="date">Date: 2018-11-21</p>
<p class="author">Author: gdme1320</p>
<p class="validation"><a href="http://validator.w3.org/check?uri=referer">Validate</a></p>
</div>
